package ray;

import ray.math.*;

/**
 * Represents a simple camera.
 */
public class Camera {
	
	/*
	 * Fields that are read in from the input file to describe the camera.
	 * You'll probably want to store some derived values to make ray generation easy.
	 */
	
	protected final Point3 viewPoint = new Point3();
	public void setViewPoint(Point3 viewPoint) { this.viewPoint.set(viewPoint); }
	
	protected final Vector3 viewDir = new Vector3(0, 0, -1);
	public void setViewDir(Vector3 viewDir) { this.viewDir.set(viewDir); }
	
	protected final Vector3 viewUp = new Vector3(0, 1, 0);
	public void setViewUp(Vector3 viewUp) { this.viewUp.set(viewUp); }
	
	protected final Vector3 projNormal = new Vector3(0, 0, 1);
	public void setProjNormal(Vector3 projNormal) { this.projNormal.set(projNormal); }
	
	protected double viewWidth = 1.0;
	public void setViewWidth(double viewWidth) { this.viewWidth = viewWidth; }
	
	protected double viewHeight = 1.0;
	public void setViewHeight(double viewHeight) { this.viewHeight = viewHeight; }
	
	protected double projDistance = 1.0;
	public void setprojDistance(double projDistance) { this.projDistance = projDistance; }
	
	//orthonormal basis vectors
	
	protected final Vector3 U = new Vector3();
    protected final Vector3 V = new Vector3();
    protected final Vector3 W = new Vector3();
    
    
    public void setup() {
        projNormal.normalize();
        viewUp.normalize();
        viewDir.normalize();

        W.set(projNormal);
        W.normalize();
        
        
        U.cross(viewUp, W);
        U.normalize();


        V.cross(W, U);
        V.normalize();
    }
    public void makeRay(Ray outRay, double uU, double uV) {

        Point3 centerOfImage = new Point3(viewPoint);

        double leftExtent = -(viewWidth / 2);
        double bottomExtent = -(viewHeight / 2);

        double rightExtent = viewWidth / 2;
        double topExtent = viewHeight / 2;

        //convert from camera u/v coordinates to World u/v coordinates
        double wU = leftExtent + (rightExtent - leftExtent) * uU;
        double wV = bottomExtent + (topExtent - bottomExtent) * uV;

        Point3 s = new Point3();
        centerOfImage.scaleAdd(projDistance, viewDir);
        s.set(centerOfImage);

        s.scaleAdd(wU, U);
        s.scaleAdd(wV, V);

        Vector3 direction = new Vector3();
        direction.sub(s, viewPoint);
        direction.normalize();

        outRay.set(viewPoint, direction);
    }
}